上图
首先我们分析做出类似这种效果需要什么条件
- 首先,肯定是两种color originalColor和changeColor
- 其次,是两个paint 绘制上下两层文字
那要怎么做才能来实现上面的效果呢?
通过canvas.clipRect方法,即可控制上下两层的不同的切割区域。
具体代码如下:
1.在resource中创建attrs.xml文件
<resources>
<declare-styleable name="GradienTextView">
<attr format="color" name="original_color"/>
<attr format="color" name="change_color"/>
</declare-styleable>
</resources>
2.新建GradienTextView集成TextView,重写onDrow方法
public GradienTextView(Context context) {
this(context,null);
}
public GradienTextView(Context context, AttributeSet attrs) {
this(context, attrs,0);
}
public GradienTextView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
TypedArray td = context.obtainStyledAttributes(attrs, R.styleable.ChangeTextView);
mOriginalColor = td.getColor(R.styleable.ChangeTextView_originalCololr, Color.BLACK);
mChangeColor = td.getColor(R.styleable.ChangeTextView_changeColor, Color.RED);
td.recycle();
//根据颜色获取画笔
mOriginalPaint = getPaintByColor(mOriginalColor);
mChangePaint=getPaintByColor(mChangeColor);
}
private Paint getPaintByColor(int color){
Paint paint=new Paint();
paint.setColor(color);
paint.setAntiAlias(true);
paint.setDither(true);//防抖动
paint.setTextSize(getTextSize());
return paint;
}
@Override
protected void onDraw(Canvas canvas) {
//切割区域的大小
float middle = mCurrentProgress * getWidth();
Paint.FontMetricsInt fontMetricsInt = mOriginalPaint.getFontMetricsInt();
//绘制文字的基线
baseLine = (fontMetricsInt.bottom - fontMetricsInt.top) / 2 - fontMetricsInt.bottom + getHeight()/2
+getPaddingTop()/2-getPaddingBottom()/2;
//保存画布 如果不保存画布进行操作,会造成画布丢失是不可逆的
canvas.save();
//从原点开始,切割一半大小的区域
canvas.clipRect(0,0,middle,getHeight());
canvas.drawText(getText().toString(), getPaddingLeft(),baseLine,mOriginalPaint);
canvas.restore();
//此时,操作下半部分区域
canvas.save();
canvas.clipRect(middle,0,getWidth(),getHeight());
canvas.drawText(getText().toString(), getPaddingLeft(),baseLine,mChangePaint);
canvas.restore();
}
3.设置进度,重绘视图
private float mCurrentProgress=0f;
public void setCurrentProgress(float currentProgress){
mCurrentProgress=currentProgress;
invalidate();
}